package com.woniu.gateway.filter;

import com.woniu.common.exception.Assert;
import com.woniu.common.utils.JwtTemplate;
import com.woniu.common.utils.TokenUtils;
import com.woniu.gateway.config.IgnorePathConfig;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.List;

/**
 * GlobalFilter
 */
@Configuration
public class AuthFilter implements GlobalFilter {

    @Autowired
    private IgnorePathConfig ignorePathConfig;
    @Autowired
    private JwtTemplate jwtTemplate;
    @Autowired
    private RedisTemplate redisTemplate;

    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //请求对象
        ServerHttpRequest request = exchange.getRequest();
        //响应对象
        ServerHttpResponse response = exchange.getResponse();
        //获取白名单
        List whiteList = ignorePathConfig.getWhiteList();
        //1.判断请求是否在白名单内
        String path = request.getURI().getPath();
        if (whiteList.contains(path)) {
            return chain.filter(exchange);
        }
        //2获取token
        String authorization = request.getHeaders().getFirst("Authorization");
        if (authorization == null) {
            Assert.error("token不存在...");
        }
        //3.校验token
        String token = authorization.substring(7);
        boolean verify = jwtTemplate.verify(token);
        if (!verify) {
            Assert.error("token校验失败");
        }
        //4、解析获取token数据： userId, 校验token是否过期
        Number userId = (Number) jwtTemplate.parseToken(token,"userId");
        String key = "user:token:" + userId.toString();
        String redisToken = (String) redisTemplate.opsForValue().get(key);
//        if (redisToken == null) {
//            Assert.error("token已过期...");
//        }
        //05、续期
        redisTemplate.expire(
                key,
                Duration.ofMinutes(30)
        );
        //06 网关中重写请求头，让请求头携带userId，再转发到微服务，这样在微服务中就可以直接获取登录用户id
        request.mutate().header("userId",userId.toString());

        //7、微服务直接从请求头获取用户id
        return chain.filter(exchange);
    }
}
